<html>
    <head>
        <meta charset="utf-8">
        <title>Flask-Admin 增加自定义Action</title>
        <link rel="stylesheet" href="../assets/stylesheets/global.css">
        <link rel="stylesheet" href="../assets/stylesheets/words.css">
        <link rel="stylesheet" href="../assets/stylesheets/monokai.css">
        <link rel="stylesheet" href="../assets/stylesheets/table.css">
        <link rel="shortcut icon" href="../assets/images/favicon.ico" type="image/x-icon">
        <link rel="icon" href="../assets/images/favicon.ico" type="image/x-icon">
        <script>
            // 统计代码
            (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
                (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
                m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
                })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

            ga('create', 'UA-93231524-1', 'auto');
            ga('send', 'pageview');
        </script>
    </head>
    <body>
        <div id="header">
            <a href="../index.html"><div id="logo">JG</div></a>
        </div>
        <div id="container" class="typo">
            <div id="article">
                <h1>Flask-Admin 增加自定义Action</h1>
                <h4>Posted May 12, 2017</h4>

                <p>默认情况下, Flask Admin提供了两个Row Action, 即delete和edit. 但是大多数情况下, 这些并不能满足有其他快捷操作需求, 好在Flask Admin提供增加这种按钮的接口.</p>

<h2><code>UserView.py</code></h2>

<p>这是我原本的Admin ModelView实现, 很明显我没有对row actions做任务的定制.</p>
<div class="code-wrapper"><span class="lang-label">Python</span><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">UserView</span><span class="p">(</span><span class="n">ModelView</span><span class="p">):</span>
    <span class="n">column_default_sort</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span>
    <span class="n">column_list</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="s1">&#39;roles&#39;</span><span class="p">)</span>
    <span class="n">column_filters</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">)</span>
    <span class="n">form_create_rules</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;avatar&#39;</span><span class="p">,</span> <span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="s1">&#39;roles&#39;</span><span class="p">)</span>
</pre></div>
</div>
<h2>增加row action按钮</h2>

<p>我们可以通过<a href="https://flask-admin.readthedocs.io/en/latest/api/mod_model/#flask_admin.model.BaseModelView.column_extra_row_actions"><code>column_extra_row_actions</code></a>属性增加row action. </p>
<div class="code-wrapper"><span class="lang-label">Python</span><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">flask_admin.model.template</span> <span class="kn">import</span> <span class="n">EndpointLinkRowAction</span>

<span class="k">class</span> <span class="nc">UserView</span><span class="p">(</span><span class="n">ModelView</span><span class="p">):</span>
    <span class="n">column_default_sort</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span>
    <span class="n">column_list</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="s1">&#39;roles&#39;</span><span class="p">)</span>
    <span class="n">column_filters</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">)</span>
    <span class="n">form_create_rules</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;avatar&#39;</span><span class="p">,</span> <span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="s1">&#39;roles&#39;</span><span class="p">)</span>

    <span class="n">column_extra_row_actions</span> <span class="o">=</span> <span class="p">[</span>
        <span class="n">EndpointLinkRowAction</span><span class="p">(</span>
            <span class="s1">&#39;off glyphicon glyphicon-off&#39;</span><span class="p">,</span>
            <span class="s1">&#39;user.activate_user_view&#39;</span><span class="p">,</span>
        <span class="p">)</span>
    <span class="p">]</span>
</pre></div>
</div><blockquote class="blockquote-normal">
                <p>Flask-admin提供了row action的模版, 其中上面使用的<code>EndpointLinkRowAction</code>, 传入的是一个view(<code>user.activate_user_view</code>). 它是定义在UserView上的一个view方法(请看下面代码). 同时row action也有<code>LinkRowAction</code>类型, 它接受icon class和一个url. 另外它支持更多的类型, 请看<a href="https://github.com/flask-admin/flask-admin/blob/master/flask_admin/model/template.py#L66">这里:Github</a></p></blockquote>
<h2>增加对应的endpoint</h2>

<p>在上面我们增加了一个<code>EndpointLinkRowAction</code>, 但是我们还没有定义动作具体的逻辑. 下面我们定义<code>user.activate_user_view</code>来接收这个动作的参数, 并实现相应的功能.</p>
<div class="code-wrapper"><span class="lang-label">Python</span><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">UserView</span><span class="p">(</span><span class="n">ModelView</span><span class="p">):</span>
    <span class="n">column_default_sort</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span>
    <span class="n">column_list</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="s1">&#39;roles&#39;</span><span class="p">)</span>
    <span class="n">column_filters</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">)</span>
    <span class="n">form_create_rules</span> <span class="o">=</span> <span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="s1">&#39;avatar&#39;</span><span class="p">,</span> <span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="s1">&#39;active&#39;</span><span class="p">,</span> <span class="s1">&#39;roles&#39;</span><span class="p">)</span>

    <span class="n">column_extra_row_actions</span> <span class="o">=</span> <span class="p">[</span>
        <span class="n">EndpointLinkRowAction</span><span class="p">(</span>
            <span class="s1">&#39;off glyphicon glyphicon-off&#39;</span><span class="p">,</span>
            <span class="s1">&#39;user.activate_user_view&#39;</span><span class="p">,</span>
        <span class="p">)</span>
    <span class="p">]</span>

    <span class="nd">@expose</span><span class="p">(</span><span class="s1">&#39;/activate/&#39;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">(</span><span class="s1">&#39;GET&#39;</span><span class="p">,))</span>
    <span class="k">def</span> <span class="nf">activate_user_view</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">            Activate user model view. Only GET method is allowed.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">return_url</span> <span class="o">=</span> <span class="n">get_redirect_target</span><span class="p">()</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_url</span><span class="p">(</span><span class="s1">&#39;.index_view&#39;</span><span class="p">)</span>

        <span class="nb">id</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="s2">&quot;id&quot;</span><span class="p">]</span>
        <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_one</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">model</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">flash</span><span class="p">(</span><span class="n">gettext</span><span class="p">(</span><span class="s1">&#39;用户不存在&#39;</span><span class="p">),</span> <span class="s1">&#39;error&#39;</span><span class="p">)</span>
            <span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">return_url</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">model</span><span class="o">.</span><span class="n">active</span><span class="p">:</span>
            <span class="n">flash</span><span class="p">(</span><span class="n">gettext</span><span class="p">(</span><span class="s1">&#39;已经激活， 无需重复激活.&#39;</span><span class="p">),</span> <span class="s1">&#39;warning&#39;</span><span class="p">)</span>
            <span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">return_url</span><span class="p">)</span>

        <span class="n">model</span><span class="o">.</span><span class="n">active</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="n">model</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>

        <span class="n">flash</span><span class="p">(</span><span class="n">gettext</span><span class="p">(</span><span class="s1">&#39;已激活&#39;</span><span class="p">),</span> <span class="s1">&#39;success&#39;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">return_url</span><span class="p">)</span>
</pre></div>
</div>
<p>到此我们增加一个<code>快速激活用户</code>的方法就完成了.</p>

<p><p class="hassubimage"><img src="/uploads/images/flask-admin-add-custom-row-action.jpeg" alt="增加后的动作列表"></p>
</p>

            </div>
            <div id="footer">
                <a href="../words.html"><div id="more-words">MORE WORDS</div></a>
            </div>
        </div>
    </body>
</html>